#!/usr/bin/env python

import simplejson
import os, sys
import shutil
import tempfile

import twisted
from twisted.words.protocols import irc
from twisted.internet import protocol, reactor
from twisted.web import server, resource

class IRCBot(irc.IRCClient):
    def _get_nickname(self):
        return self.factory.nickname
    nickname = property(_get_nickname)

    def signedOn(self):
        for channel in self.factory.channels: 
            self.join(channel[0])
        print "Signed on as %s." % (self.nickname,)

    def joined(self, channel):
        print "Joined %s." % (channel,)

    def privmsg(self, user, channel, msg):
        print "PM:", msg

class IRCBotFactory(protocol.ReconnectingClientFactory):
    protocol = IRCBot

    def __init__(self, channels, nickname):
        self.channels = channels
        self.nickname = nickname
        self.irc_bot = None

    def clientConnectionLost(self, connector, reason):
        print "Lost connection (%s), reconnecting." % (reason,)
        protocol.ReconnectingClientFactory.clientConnectionLost(self, connector, reason)

    def clientConnectionFailed(self, connector, reason):
        print "Could not connect: %s" % (reason,)
        protocol.ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)

    def buildProtocol(self, addr):
        self.irc_bot = protocol.ReconnectingClientFactory.buildProtocol(self, addr)
        return self.irc_bot

class Simple(resource.Resource):
    isLeaf = True

    def __init__(self, client_factories):
        self.client_factories = client_factories

    def render_GET(self, request):
        print "GET", request.path
        return "Please POST to this url."
        # should be an error code specifically for this

    def render_POST(self, request):
        print "POST", request.path
        request.content.seek(0)
        post_body = request.content.read()
        import settings
        if request.path in settings.connections:
            formatter, channel_ids = settings.connections[request.path]
            if formatter.auth(request.requestHeaders, post_body):
                messages = formatter.format(post_body)
                for channel_id in channel_ids:
                    network, channel = settings.channels_by_id[channel_id]
                    for message in messages:
                        self.client_factories[network].irc_bot.msg(channel, message, 440)
                return "Okay."
            else:
                print "no auth"
                return "Not authorised." #
        else:
            print "404 post"
            return "Bad." # should be 404

def complete_settings(settings):
    settings.channels_by_id = {}
    for network, channels in settings.channels.iteritems():
        for channel in channels:
            settings.channels_by_id[channel[1]] = (network, channel[0])

def main(argv):
    tempdir = tempfile.mkdtemp()
    sys.path.insert(0, tempdir)
    shutil.copyfile(argv[1], os.path.join(tempdir, 'settings.py'))
    import settings
    complete_settings(settings)
    irc_client_factories = {}
    for network, channels in settings.channels.iteritems():
        network_bits = network.split(':')
        factory = IRCBotFactory(channels, settings.username)
        reactor.connectTCP(network_bits[0], 6667 if len(network_bits) == 1 else int(network_bits[1]), factory)
        irc_client_factories[network] = factory
    site = server.Site(Simple(irc_client_factories))
    reactor.listenTCP(8080, site)
    reactor.run()

if __name__ == "__main__":
    sys.exit(main(sys.argv))
